package com.yesep.learn.jwt.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import com.yesep.learn.jwt.config.JWTTokenConfig;

import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;

/**
 */
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {

	private JWTTokenConfig jwtTokenConfig;

	public JWTAuthenticationFilter(AuthenticationManager authenticationManager, JWTTokenConfig jwtTokenConfig) {
		super(authenticationManager);
		this.jwtTokenConfig = jwtTokenConfig;
	}

	public JWTAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
		super(authenticationManager, authenticationEntryPoint);
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
		String token = jwtTokenConfig.parseToken(request);
		// System.out.println(request.getRequestURI());
		if (token != null && SecurityContextHolder.getContext().getAuthentication() == null) {

			Claims claims = jwtTokenConfig.getClaimsFromToken(token);
			logger.debug("checking authentication " + claims);
			if (claims != null) {
				String username = (String) claims.get(JWTTokenConfig.CLAIM_KEY_USERNAME);
				if (StrUtil.isNotBlank(username)) {
					List<String> auths = (List<String>) claims.get(JWTTokenConfig.CLAIM_KEY_AUTH);
					List<GrantedAuthority> authorities = new ArrayList<>();
					for (String ga : auths) {
						authorities.add(new SimpleGrantedAuthority(ga));
					}
					UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, "", authorities);
					authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
					logger.debug("authenticated user " + username + ", setting security context");
					SecurityContextHolder.getContext().setAuthentication(authentication);
				}
			}
		}

		chain.doFilter(request, response);
	}

}